import {t} from 'elysia'
import {ElysiaApp} from '..'
import {DWError, ForbiddenError, isAdmin} from '../utils/auth'
import {isEmpty} from 'lodash'
import {sysMenu, sysRole, sysRoleMenu} from '../schema/schema'
import {eq, like, and, ne, sql, inArray} from 'drizzle-orm'
import {toSql} from '../utils/dw'
import {union} from 'drizzle-orm/mysql-core'

const addSchema = t.Object({
  pid: t.Number(),
  type: t.Number(),
  icon: t.Optional(t.String()),
  name: t.String(),
  perms: t.String(),
  isShow: t.Optional(t.Number({minimum: 1, maximum: 2})),
  order: t.Number(),
})

const updSchema = t.Intersect([addSchema, t.Object({id: t.Number()})])

export default (app: ElysiaApp) =>
  app
    // 获取全部菜单列表
    .get(
      '/page/list',
      async ({db, query}) => {
        const {name, status} = query
        return await db
          .select()
          .from(sysMenu)
          .where(
            and(
              toSql(name, e => like(sysMenu.name, `%${e}%`)),
              toSql(status, e => eq(sysMenu.isShow, e)),
            ),
          )
      },
      {
        query: t.Object({
          name: t.Optional(t.String()),
          status: t.Optional(t.Numeric({minimum: 1, maximum: 2})),
        }),
      },
    )
    .get('/list', async ({db}) => await db.select({id: sysMenu.id, pid: sysMenu.pid, name: sysMenu.name}).from(sysMenu).where(ne(sysMenu.type, 2)))
    .get('/api/list', async ({db}) => {
      const {id, pid, name, type} = sysMenu
      return await union(
        db
          .select({id, pid, name})
          .from(sysMenu)
          .where(inArray(id, sql`( SELECT parent_id FROM sys_menu  WHERE type = 2 )`)),
        db.select({id, pid, name}).from(sysMenu).where(eq(type, 2)),
      )
    })
    .post(
      '/add',
      async ({db, body}) => {
        const {pid, type, icon, name, perms, isShow, order} = body
        const _menu = await db.query.sysMenu.findFirst({where: eq(sysMenu.perms, perms)})
        if (_menu) throw new ForbiddenError('此权限标识已存在，请勿重新添加')
        if (type !== 2) {
          if (isEmpty(icon)) throw new DWError('Unprocessable Content', 'icon is required')
          if (!isShow) throw new DWError('Unprocessable Content', 'isShow is required')
        }
        await db.transaction(async tx => {
          const data = await tx.insert(sysMenu).values({pid, type, icon, name, perms, isShow, order}).$returningId()
          const role = await tx.query.sysRole.findFirst({where: eq(sysRole.name, 'admin')})
          await tx.insert(sysRoleMenu).values({roleId: role!.id, menuId: data[0].id})
        })
        return '菜单新增成功'
      },
      {body: addSchema},
    )
    .patch(
      '/upd',
      async ({body, db}) => {
        const {id, pid, type, icon, name, perms, isShow, order} = body
        const _menu = await db.query.sysMenu.findFirst({where: eq(sysMenu.perms, perms)})
        const _curMenu = await db.query.sysMenu.findFirst({where: eq(sysMenu.id, id)})
        if (_menu && _curMenu!.perms !== _menu.perms) throw new ForbiddenError('此权限标识已存在，请勿修改')
        if (type !== 2) {
          if (isEmpty(icon)) throw new DWError('Unprocessable Content', 'icon is required')
          if (!isShow) throw new DWError('Unprocessable Content', 'isShow is required')
        }
        await db.update(sysMenu).set({pid, type, icon, name, perms, isShow, order}).where(eq(sysMenu.id, id))
        return '菜单修改成功'
      },
      {body: updSchema},
    )
    .delete(
      '/del',
      async ({body, db, store: {curUser}}) => {
        if (!(await isAdmin(db, curUser))) throw new ForbiddenError('普通用户不可删除，请联系管理员操作')
        const {id} = body
        await db.transaction(async tx => {
          await tx.delete(sysRoleMenu).where(eq(sysRoleMenu.menuId, id))
          await tx.delete(sysMenu).where(eq(sysMenu.id, id))
        })
        return '菜单删除成功'
      },
      {body: t.Object({id: t.Numeric()})},
    )
